//
//  TrainingData.h
//  RandomForest-AndreaBalboni
//
//  Created by Andrea Balboni on 05/04/12.
//  Copyright (c) 2012 Università degli Studi di Modena e Reggio Emilia. All rights reserved.
//

#ifndef RandomForest_AndreaBalboni_TrainingData_h
#define RandomForest_AndreaBalboni_TrainingData_h

#include "MyRecord.h"
#include <vector>
#include <iostream>
#include <fstream>
#include <map>
#include <opencv2/opencv.hpp>


template <typename _T>
class TrainingData {
    
private:
    std::vector<MyRecord<_T> > _trainingData;
    unsigned int _featureSpaceDimension;
    
    std::map<int,int> _numClass; //istogramma delle classi
    
    //Legge un valore da file
    std::string readStringVal(std::ifstream &file);
    
    //Restituisce un valore da lettura da file
    _T readVal(std::ifstream &file);
    
        
public:
    typedef typename std::vector<_T>::iterator _TVectorIterator;
    typedef typename std::vector<MyRecord<_T> >::iterator VectorRecordIterator;
    //Costruttore per il dataset
    TrainingData():_trainingData(0){}
    
    //Restituisce la dimensione del dataset
    int size();
    
    //Ridimensiona _trainingData
    void resize(int size);
    
    //Imposta la dimensionalita' in _featureSpaceDimension
    void setFeatureSpaceDimension(unsigned int dimensionality);
    
    //Restituisce la dimensionalita' da _featureSpaceDimension
    unsigned int getFeatureSpaceDimension();
    
    //Restituisce il valore massimo delle features di ogni record in posizione specificata
    _T getMaxValAtFeatureIndex(unsigned int featureIndex);
    
    //Restituisce il valore minimo delle features di ogni record in posizione specificata
    _T getMinValAtFeatureIndex(unsigned int featureIndex);
    
    //Imposta contemporaneamente i valori massimo e minimo in due variabili passate per reference
    //per le features in ogni record in una determinata posizione
    void getMinMaxValAtFeatureIndex(unsigned int featureIndex, _T &minVal, _T &maxVal);
    
    //Valori delle features all'indice specificato
    void getFeatureValueOnDimensionD(	std::vector<std::pair<_T, unsigned int> > &v, 
                                std::vector<unsigned int> &indexes, 
                                unsigned int splitDim);

    //Ottengo un record da lettura da file
    MyRecord<_T> readTrainingRecord(std::ifstream &file, int nfeatures, int nclasses);
    
    //Leggo l'intero dataset e lo inserisco nella apposita struttura dati
    bool readData(std::string filename);

    //Restituisce una reference ad un record in posizione specificata nel dataset
    MyRecord<_T>& getRecord(unsigned int i);
    
    //Restituisce una reference ad un record in posizione specificata nel dataset
    void getRecordMat(unsigned int i, cv::Mat_<double> &r);
	
    //Aggiunge un record al dataset.
    void push_Record(MyRecord<_T> &record);
    
    //Legge il dataset da file
    bool readTrainingData(std::string filename);
    
    //Calcola la distribuzione delle classi all'interno del dataset
    std::map<int,double> classProbDist();
    
    /* Iteratori */
    
    VectorRecordIterator begin() {
        return _trainingData.begin();
	}
    
    VectorRecordIterator end() {
		return _trainingData.end();
	}
    
};

#endif
